package com.cooperate.fly.service.buildDB.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.cooperate.fly.bo.Case;
import com.cooperate.fly.bo.CaseWithBLOBs;
import com.cooperate.fly.bo.Field;
import com.cooperate.fly.bo.Schema;
import com.cooperate.fly.bo.Table;
import com.cooperate.fly.bo.TableWithBLOBs;
import com.cooperate.fly.mapper.CaseMapper;
import com.cooperate.fly.mapper.DataRightMapper;
import com.cooperate.fly.mapper.FieldMapper;
import com.cooperate.fly.mapper.SchemaMapper;
import com.cooperate.fly.mapper.TableMapper;
import com.cooperate.fly.service.buildDB.BuildSchemaService;
import com.cooperate.fly.web.Result;
import com.cooperate.fly.web.WebFrontHelper;
import com.google.gson.Gson;

@Service("build_schema")
public class BuildSchemaSerivceImpl implements BuildSchemaService {

	Logger log = Logger.getLogger(BuildSchemaSerivceImpl.class);

	@Resource
	private SchemaMapper schemaMapper;

	@Resource
	private CaseMapper caseMapper;

	@Resource
	private FieldMapper fieldMapper;

	@Resource
	private TableMapper tableMapper;

	@Resource
	private DataRightMapper dataRightMapper;

	@Value("#{propertiesReader['create_success']}")
	private String createSuccess;

	@Value("#{propertiesReader['create_fail']}")
	private String createFail;

	@Value("#{propertiesReader['create_same_name_node']}")
	private String createSameNameNode;

	@Value("#{propertiesReader['schema_database_type']}")
	public int schemaDatabaseType;

	@Value("#{propertiesReader['schema_catalog_type']}")
	public int schemaCatalogType;

	@Value("#{propertiesReader['case_data_type']}")
	public int caseDataType;

	@Value("#{propertiesReader['url_split_symbol']}")
	public String urlSplitSymbol;

	@Resource
	private WebFrontHelper webFrontHelper;

	@Override
	public Result createSchemaNode(Schema schema) {
		Result result = new Result();
		if (!checkName(schema)) {
			result.setSuccessful(false);
			result.setMessage(createSameNameNode);
			return result;
		}
		int res = schemaMapper.insert(schema);
		Integer sid = schema.getId();
		if ((res == 1) && (sid != null)) {
			Schema parentSchema = schemaMapper.selectByPrimaryKey(schema
					.getParentId());
			String path = null;
			if (parentSchema != null) {
				path = parentSchema.getPath();
				path += "/" + sid;
			} else {
				path = "/" + sid;
			}
			schemaMapper.updatePathById(path, sid);
			result.setMessage(createSuccess);
			result.setData(schema.getId());
		} else {
			result.setSuccessful(false);
			result.setMessage(createFail);
		}
		return result;
	}

	@Override
	public Result deleteSchemaNode(int id) {
		Result result = new Result();
		ArrayList<Schema> sumSchema = new ArrayList<Schema>();
		// delete all the field of the database, this need transaction
		if (id == 0) {
			ArrayList<Schema> rootSchemas = new ArrayList<Schema>();
			rootSchemas = schemaMapper.selectByParentId(id);
			for (Schema schema2 : sumSchema) {
				getSchemas(schema2, sumSchema);
			}
			sumSchema.addAll(rootSchemas);
		} else {
			Schema schema = schemaMapper.selectByPrimaryKey(id);
			getSchemas(schema, sumSchema);
			sumSchema.add(schema);
		}
		int count = 0;
		for (Schema schema1 : sumSchema) {
			int type = schema1.getType();
			if (type == schemaDatabaseType) {
				fieldMapper.deleteBySchemaId(schema1.getId());
				schemaMapper.dropTable("table_" + schema1.getId());
				caseMapper.deleteBySchemaId(schema1.getId());
				dataRightMapper.deleteBySchemaId(schema1.getId());
			}
			int res = schemaMapper.deleteByPrimaryKey(schema1.getId());
			if (res == 1)
				count++;
		}
		if (count == sumSchema.size()) {
			result.setMessage(createSuccess);
		} else {
			result.setMessage(createFail);
			result.setSuccessful(false);
		}
		return result;
	}

	@Override
	public Result updateSchemaNode(Schema schema) {
		Result result = new Result();
		Schema dbSchema = schemaMapper.selectByPrimaryKey(schema.getId());
		dbSchema.setName(schema.getName());
		if (!checkName(dbSchema)) {
			result.setSuccessful(false);
			result.setMessage(createSameNameNode);
			return result;
		}
		int res = schemaMapper.updateByPrimaryKey(dbSchema);
		if (res == 1) {
			result.setMessage(createSuccess);
		} else {
			result.setMessage(createFail);
			result.setSuccessful(false);
		}
		return result;
	}

	@Override
	public Result searchSchemaNode(Schema schema) {
		return null;
	}

	@Override
	public Result createSchemaTableBySId(int schemaId) {
		return null;
	}

	@Override
	public Result updateSchemaTable() {
		return null;
	}

	@Override
	public String loadSchema() {
		ArrayList<Schema> schemas = schemaMapper.selectAll();
		return webFrontHelper.buildSchemaTree(schemas);
	}

	@Override
	public Result setDatabase(int schemaId) {
		Map<String, String> params = new HashMap<String, String>();
		Result result = new Result();
		params.put("tableName", "table_" + schemaId);
		int res = schemaMapper.createTableStore(params);
		// 如果只是添加了数据表的某些项,则不创建表格而是添加,所以需要在每个case版本中添加上这个fields
		ArrayList<Field> fields = new ArrayList<Field>();
		fields = fieldMapper.selectByDId(schemaId);
		List<CaseWithBLOBs> cases = new ArrayList<CaseWithBLOBs>();
		cases = caseMapper.selectBySchemaId(schemaId, caseDataType);
		if (fields.size() > 0 && cases.size() > 0) {
			for (Field field : fields) {
				Table tableNode = tableMapper.selectByCaseIdAndFieldId("table_"
						+ schemaId, cases.get(0).getId(), field.getId());
				if (tableNode == null) {
					for (Case _case : cases) {
						TableWithBLOBs tableWithBLOBs = new TableWithBLOBs();
						tableWithBLOBs.setFieldId(field.getId());
						tableWithBLOBs.setCaseId(_case.getId());
						tableWithBLOBs.setValue(" ");
						tableWithBLOBs.setRemark2(field.getRemark3() + " ");
						tableMapper.insertIntoTable("table_" + schemaId,
								tableWithBLOBs);
					}
				} else {
					// 当单位更新的时候需要更新
					if ((tableNode.getRemark2() == null && field.getRemark3() != null)
							|| (tableNode.getRemark2() != null && field
									.getRemark3() == null)
							|| (tableNode.getRemark2() != null
									&& field.getRemark3() != null && !tableNode
									.getRemark2().equals(field.getRemark3()))) {
						for (Case _case : cases) {
							tableMapper.updateUnit("table_" + schemaId,
									field.getRemark3(), _case.getId(),
									field.getId());

						}
					}
				}
			}
		}
		result.setMessage(createSuccess);
		return result;
	}

	@Override
	public Schema selectSchemaById(int id) {
		return schemaMapper.selectByPrimaryKey(id);
	}

	@Override
	public ArrayList<Schema> selectByParentId(int parentId) {
		return schemaMapper.selectByParentId(parentId);
	}

	@Override
	public String loadPartSchema(int schemaId) {
		Schema schema = schemaMapper.selectByPrimaryKey(schemaId);
		ArrayList<Schema> schemas = new ArrayList<Schema>();
		if (schema != null) {
			schemas.add(schema);
			getSchemas(schema, schemas);
			return webFrontHelper.buildSchemaTree(schemas);
		} else {
			return null;
		}
	}

	@Override
	public String parseSchemaUrl(String path) {
		String[] schemaNames = path.split(urlSplitSymbol);
		int parentId = 0;
		String res = "";
		ArrayList<Schema> schemas = new ArrayList<Schema>();
		Schema schema = null;
		for (int i = 0; i < schemaNames.length; i++) {
			String name = schemaNames[i];
			schema = schemaMapper.selectByNameAndParentId(name, parentId);
			schemas.add(schema);
			parentId = schema.getId();
		}
		if (schema != null) {
			getSchemas(schema, schemas);
		}
		res = new Gson().toJson(schemas);
		// 获得数据库中的所有属性项目
		for (Schema sonSchema : schemas) {
			if (sonSchema.getType() == schemaDatabaseType) {
				ArrayList<Field> fields = new ArrayList<Field>();
				fields = fieldMapper.selectByDId(sonSchema.getId());
				String fieldString = new Gson().toJson(fields);
				if (fieldString != null) {
					res = res.substring(0, res.length() - 1) + ",";
					fieldString = fieldString
							.substring(1, fieldString.length());
					res += fieldString;
				}
			}
		}
		if (schemas != null) {
			return res;
		} else
			return null;
	}

	// 递归循环该节点的子节点直到叶子节点的schema节点,不包含查询节点本身
	public void getSchemas(Schema schema, ArrayList<Schema> sumSchema) {
		if (schema.getType() == schemaCatalogType) {
			ArrayList<Schema> schemas = schemaMapper.selectByParentId(schema
					.getId());
			sumSchema.addAll(schemas);
			for (Schema schema1 : schemas) {
				getSchemas(schema1, sumSchema);
			}
		}
	}

	@Override
	public boolean checkName(Schema schema) {
		ArrayList<Schema> schemas = schemaMapper.selectByParentId(schema
				.getParentId());
		if (schemas != null) {
			for (Schema s : schemas) {
				if (s.getName().equals(schema.getName())
						&& (schema.getId() != s.getId()))
					return false;
			}
		}
		return true;
	}

	@Override
	public Result getSchemaRemark3(int schemaId) {
		Result result = new Result();
		Schema schema = schemaMapper.selectByPrimaryKey(schemaId);
		if (schema != null) {
			result.setData(schema.getRemark3());
		} else {
			result.setSuccessful(false);
		}
		return result;
	}

	/**
	 * 获得数据的描述信息，remark2是图片描述信息，remark3是文本描述信息
	 * 
	 * @param schemaId
	 * @return
	 */
	@Override
	public Result getSchemaInfo(int schemaId) {
		Result result = new Result();
		Schema schema = schemaMapper.selectByPrimaryKey(schemaId);
		if (schema != null) {
			String[] infos = { schema.getRemark2(), schema.getRemark3() };
			result.setData(infos);
		} else {
			result.setSuccessful(false);
		}
		return result;
	}

	@Override
	public Result setSchemaRemark3(int schemaId, String remark3) {
		Result result = new Result();
		Schema schema = schemaMapper.selectByPrimaryKey(schemaId);
		if (schema != null) {
			schema.setRemark3(remark3);
			schemaMapper.updateByPrimaryKeyWithBLOBs(schema);
			result.setMessage(createSuccess);
		} else {
			result.setSuccessful(false);
			result.setMessage(createFail);
		}
		return result;
	}
}
